/*
 * @Author: zhang zhijiang 2824735304@qq.com
 * @Date: 2025-04-21 20:25:58
 * @LastEditors: zhang zhijiang 2824735304@qq.com
 * @LastEditTime: 2025-04-22 21:32:10
 * @FilePath: /linux/test_4_21/tcpserver.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once
#include <iostream>
#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <memory>
#include <unistd.h>
#include <vector>
#include <functional>
#include <unordered_map>
#include <sys/types.h>
#include <sys/wait.h>
#include<signal.h>
#include"Daemon.hpp"
using namespace std;
static string defaultip = "0.0.0.0";
static int defaultfd = 0;
const int backlog = 5;
//class tcpserver;
class tcpserver
{
public:
    tcpserver(uint16_t &port, const string &ip = defaultip) : _listensockfd(defaultfd), _port(port), _ip(ip)
    {
    }

    void init()
    {

        _listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensockfd < 0)
        {
            exit(1);
        }
        int opt= 1;
        setsockopt(_listensockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));//让进程绑定端口
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_port = htons(_port);
        local.sin_family = AF_INET;
        // local.sin_addr.s_addr = inet_addr(_ip.c_str());
        inet_aton(_ip.c_str(), (in_addr *)&local.sin_addr);
        // local.sin_addr.s_addr = INADDR_ANY;
        if (bind(_listensockfd, (sockaddr *)&local, sizeof(local)) < 0)
        {
            exit(2);
        }
        cout << "bind success" << endl;
        listen(_listensockfd, backlog);
    }
    void service(int sockfd, const string &ip, uint16_t &port)
    {
        // 接受
        //signal(SIGCHLD,SIG_IGN);//不用进行等待，直接忽略
        while (true)
        {
            char inbuffer[4096];
            int n = read(sockfd, inbuffer, sizeof(inbuffer));
            if (n < 0)
            {
                cout << "read error" << endl;
                break;
            }
            else if (n == 0) // 没读取到字节
            {
                cout << "client closed" << endl;
                break;
            }
            else
            {
                inbuffer[n] = 0;
                cout << "client:" << ip << "say@" << inbuffer << endl;
                string server = "server say@";
                server += inbuffer;
                write(sockfd, server.c_str(), server.size());
            }
        }

        // 处理
    }
    class threaddata
    {
        public:
        threaddata(int sockfd,const string & clientip,const uint16_t port,tcpserver*t):_clientip(clientip),_clientport(port),_sockfd(sockfd),_t(t)
        {}
        public:
        uint16_t _clientport;
        string _clientip;
        int _sockfd;
        tcpserver* _t;
    };  
    static void* routine(void* args)
    {
        pthread_detach(pthread_self());
        threaddata* td = static_cast<threaddata*>(args);
        td->_t->service(td->_sockfd,td->_clientip,td->_clientport);
        delete td;
        close(td->_sockfd);
        return nullptr;
    }
    void start()
    {
        Daemon();
        for (;;)
        {
            // cout<<"tcpserver is running:"<<endl;
            sockaddr_in client;
            socklen_t len = sizeof(client);
            int sockfd = accept(_listensockfd, (sockaddr *)&client, &len);
            if (sockfd < 0)
                continue;
            // cout<<"get a new link..."<<endl;
            char clientip[32];
            inet_ntop(AF_INET, &client.sin_addr, clientip, sizeof(clientip));
            uint16_t port = ntohs(client.sin_port);
            // version 1 单进程版本
            //    service(sockfd,clientip,port);
            //    close(sockfd);
            // version 2 多进程版本
        //     pid_t tid = fork();
        //     if (tid == 0)
        //     {
        //         close(_listensockfd);
        //         // 子进程
        //         if (fork() > 0)
        //             exit(1); // 子进程创建孙子进程，并将子进程退出，孙子进程由操作系统领养
        //         // 孙子进程
        //         service(sockfd, clientip, port);
        //         close(sockfd);
        //         exit(14);
        //     }
        //     // 父进程
        //     pid_t waitid = waitpid(tid,nullptr,0);//阻塞等待
        //         sleep(1);
                //version 3 多线程版本
                threaddata* td = new threaddata(sockfd,clientip,port,this);
                pthread_t tid;
                pthread_create(&tid,nullptr,routine,td);
               // pthread_join(tid,nullptr);
         }

    }
    ~tcpserver()
    {

    }

private:
    int _listensockfd;
    uint16_t _port;
    string _ip;
};